<!DOCTYPE HTML>
<script src="../../../resources/js-test.js"></script>
<script src="../resources/input-modifiers.js"></script>
<style>
div.box {
  margin: 10px;
  padding: 50px;
  float: left;
}
</style>

<div id="target" class="box" style="background-color:red">
</div>

<div id="console"></div>

<script>
// TODO(crbug.com/1076938): This test cannot be automated using current test_driver APIs.

window.name = "mainWindow";
description("Verifies that pointer event parameters are correct when fired through mouse events.");

var checkKeyModifiers = false;

var inputPointerType = "";

var pointerType = "";
var penId = 0;
var penPressure = 0;
var penTiltX = 0;
var penTiltY = 0;

var testEventList = ["mouseenter", "mouseleave", "mouseover", "mouseout", "mouseup", "mousedown", "mousemove",
                   "pointerenter", "pointerleave", "pointerover", "pointerout", "pointerup", "pointerdown", "pointermove"];
var lastPointerEvents = [];

var numericAttributes = [
    "clientX",
    "clientY",
    "layerX",
    "layerY",
    "movementX",
    "movementY",
    "offsetX",
    "offsetY",
    "pageX",
    "pageY",
    "screenX",
    "screenY",
    "x",
    "y",
    "button",
    "buttons",
    "pressure",
    "tiltX",
    "tiltY",
    "width",
    "height",
];

function getExpectedNumericAttributeValueForPE(mouseEvent, attribute) {
  var expectedValue = eval("mouseEvent." + attribute);

  // Fix expectedValue for the cases where PE & ME differs
  if (attribute == "button") {
    if (mouseEvent.type != "mousedown" && mouseEvent.type != "mouseup")
      expectedValue = -1;
    else if (inputPointerType == "eraser")
      expectedValue = 5;
  } else if (attribute == "buttons") {
    if (inputPointerType == "eraser" && mouseEvent.type == "mousedown")
      expectedValue = 32;
  } else if (attribute == "width" || attribute == "height") {
    expectedValue = 1;
  } else if (attribute == "pressure") {
    if (pointerType == "mouse")
      expectedValue = (mouseEvent.buttons == 0)? 0.0 : 0.5;
    else
      expectedValue = penPressure;
  } else if (attribute == "tiltX") {
    expectedValue = (pointerType == "mouse")? 0 : penTiltX;
  } else if (attribute == "tiltY") {
    expectedValue = (pointerType == "mouse")? 0 : penTiltY;
  }
  return expectedValue;
}

function init() {
  var targetDiv = document.getElementById("target");

  testEventList.forEach(function(eventName) {

    targetDiv.addEventListener(eventName, function(event) {

      debug("Received " + event.type);

      if (event.type.startsWith("pointer"))
        lastPointerEvents.push(event);
      else {
        if (event.type == "mouseout" || event.type == "mouseover") {
          shouldBeEqualToNumber("lastPointerEvents.length", 2);
        } else {
          shouldBeEqualToNumber("lastPointerEvents.length", 1);
        }
        shouldBeEqualToString("lastPointerEvents[0].type", event.type.replace("mouse", "pointer"));

        if (!checkKeyModifiers) {

          if (lastPointerEvents[0].type=="pointerenter" || lastPointerEvents[0].type=="pointerleave") {
            shouldBeFalse("lastPointerEvents[0].bubbles");
            shouldBeFalse("lastPointerEvents[0].cancelable");
          } else {
            shouldBeTrue("lastPointerEvents[0].bubbles");
            shouldBeTrue("lastPointerEvents[0].cancelable");
          }

          shouldBeTrue("lastPointerEvents[0].composed");
          shouldBeEqualToNumber("lastPointerEvents[0].detail", 0);

          shouldBeEqualToNumber("lastPointerEvents[0].pointerId",
              (pointerType == "mouse")? 1 : penId);
          shouldBeEqualToString("lastPointerEvents[0].pointerType", pointerType);
          shouldBeTrue("lastPointerEvents[0].isPrimary");

          numericAttributes.forEach(function(attribute) {
            var expectedValue = getExpectedNumericAttributeValueForPE(event, attribute);
            shouldBeEqualToNumber("lastPointerEvents[0]." + attribute, expectedValue);
          });

          shouldBeEqualToString("lastPointerEvents[0].view.name", "mainWindow");

        } else {

          forEachModifier(function(attr, modifierName) {
            var getModifierStateStr = ".getModifierState('" + modifierName + "');"
            if (eval("event" + getModifierStateStr))
              shouldBeTrue("lastPointerEvents[0]" + getModifierStateStr);
            else
              shouldBeFalse("lastPointerEvents[0]" + getModifierStateStr);
          });

        }

        lastPointerEvents.splice(0, 1);
      }
    });

  });
}

function runMouseTests(x, y) {
  debug("===== mouse tests =====");
  pointerType = "mouse";

  debug("--- move mouse into target ---");
  eventSender.mouseMoveTo(x + 5, y + 5);
  debug("");

  debug("--- move within target ---");
  eventSender.mouseMoveTo(x + 7, y + 15);
  eventSender.mouseMoveTo(x + 5, y + 5);
  debug("");

  debug("--- click left/right/back/forward button ---");
  // TODO(mustaq): Skip middle button because it triggers autoscroll. Consider
  // bringing it back if we choose to prevent autoscrolling by canceling middle
  // mousedown. crbug.com/644488.
  eventSender.mouseDown(0);
  eventSender.mouseUp(0);
  eventSender.mouseDown(2);
  eventSender.mouseUp(2);
  eventSender.mouseDown(3);
  eventSender.mouseUp(3);
  eventSender.mouseDown(4);
  eventSender.mouseUp(4);
  debug("");

  debug("--- click with each modifier ---");
  checkKeyModifiers = true;
  forEachModifier(function(attr, modifierName, eventSenderName) {
    eventSender.mouseDown(0, [eventSenderName]);
    eventSender.mouseUp(0, [eventSenderName]);
  });
  checkKeyModifiers = false;
  debug("");

  debug("--- move mouse out of target ---");
  eventSender.mouseMoveTo(x - 5, y - 5);

  debug("");
}

function runPenTests(x, y, id, eraseMode) {
  debug("===== pen tests " + (eraseMode? "(erase mode)" : "(draw mode)") + " =====");
  pointerType = "pen";
  inputPointerType = eraseMode? "eraser" : "pen";
  penId = id;
  penPressure = 0.0;
  penTiltX = 0;
  penTiltY = 0;

  debug("--- move pen into target ---");
  eventSender.mouseMoveTo(x + 5, y + 5, [], inputPointerType, penId, penPressure, penTiltX, penTiltY);
  debug("");

  debug("--- move within target & tap ---");
  penTiltX = 45;
  penTiltY = -34;
  eventSender.mouseMoveTo(x + 15, y + 15, [], inputPointerType, penId, penPressure, penTiltX, penTiltY);
  penPressure = 0.75;
  eventSender.mouseDown(0, [], inputPointerType, penId, penPressure, penTiltX, penTiltY);
  penPressure = 0.0;
  eventSender.mouseUp(0, [], inputPointerType, penId, penPressure, penTiltX, penTiltY);

  debug("--- move pen out of target ---");
  eventSender.mouseMoveTo(x - 5, y - 5, [], inputPointerType, penId, penPressure, penTiltX, penTiltY);
  eventSender.mouseLeave(inputPointerType, penId);
  debug("");
}

function runAllTests() {
  var rect = document.getElementById("target").getBoundingClientRect();

  runMouseTests(rect.left, rect.top);
  runPenTests(rect.left, rect.top, 2, false);
  runPenTests(rect.left, rect.top, 3, true);
}

init();
if (window.eventSender)
  runAllTests();
else
  debug("This test requires eventSender");

</script>
